package com.ruoyi.file.controller;

import com.obs.services.model.PartEtag;
import com.ruoyi.file.domain.MergeFileParams;
import com.ruoyi.file.service.IHuaWeiObsService;
import com.ruoyi.system.api.params.UploadChunkParams;
import com.ruoyi.system.api.params.UploadFileParams;
import com.ruoyi.system.api.vo.UploadFileVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.rmi.ServerException;

/**
 * 文件请求处理
 *
 * @author ruoyi
 */
@Api(tags = "文件请求处理")
@RestController
public class SysFileController {

    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);

    @Resource
    private ISysFileService sysFileService;
    @Resource
    private IHuaWeiObsService huaWeiObsService;

    /**
     * 文件上传请求
     */
    @ApiOperation("文件上传请求")
    @PostMapping("upload")
    public R<SysFile> upload(MultipartFile file) {
        try {
            // 上传并返回访问地址
            String url = sysFileService.uploadFile(file);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(url));
            sysFile.setUrl(url);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 华为云文件上传请求，小文件
     */
    @ApiOperation("华为云文件上传请求，小文件")
    @PostMapping("/huawei/upload")
    public R<SysFile> huaweiUpload(@Valid UploadFileParams uploadFileParams) {
        try {
            //上传并返回访问地址
            String url = huaWeiObsService.uploadFile(uploadFileParams);
            return R.ok(SysFile.builder()
                    .name(uploadFileParams.getFile().getOriginalFilename())
                    .url(url)
                    .build());
        } catch (Exception e) {
            log.error("----------------------------------------------------------------------------------上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 华为云文件分片上传请求，大文件
     */
    @ApiOperation("华为云文件分片上传请求，大文件")
    @PostMapping("/huawei/sharding/upload")
    public R<SysFile> huaweiShardingUpload(@Valid UploadFileParams uploadFileParams) {
        try {
            //上传并返回访问地址
            String url = huaWeiObsService.huaweiShardingUpload(uploadFileParams);
            return R.ok(SysFile.builder()
                    .name(uploadFileParams.getFile().getOriginalFilename())
                    .url(url)
                    .build());
        } catch (Exception e) {
            log.error("--------------------------------------------------------------------------华为云文件分片上传失败", e);
            return R.fail(e.getMessage());
        }
    }

    /**
     * 华为云获取上传组id
     *
     * @param biz              文件上传前缀
     * @param originalFilename 文件名
     * @return 上传文件信息
     */
    @ApiOperation("华为云获取上传组id")
    @GetMapping("/huawei/get/upload/id")
    public R<UploadFileVO> getUploadId(@RequestParam String biz, @RequestParam String originalFilename) {
        try {
            UploadFileVO uploadFile = huaWeiObsService.getUploadId(biz, originalFilename);
            return R.ok(uploadFile);
        } catch (Exception e) {
            return R.fail("获取上传组id失败：" + e.getMessage());
        }
    }

    /**
     * 华为云上传分片
     * 需要指定uploadId，同时我们要将返回的分片信息PartETag序列化保存数据库，用于后续的文件合并
     *
     * @param uploadChunkParams 分片上传参数
     * @return 分片信息
     */
    @ApiOperation("华为云上传分片")
    @PostMapping("/huawei/upload/chunk")
    public R<PartEtag> uploadChunk(@Valid UploadChunkParams uploadChunkParams) {
        try {
            PartEtag partEtag = huaWeiObsService.uploadChunk(uploadChunkParams);
            return R.ok(partEtag);
        } catch (ServerException e) {
            return R.fail("华为云上传分片失败：" + e.getMessage());
        }
    }

    /**
     * 华为云合并分片
     * 通过传递保存分片的PartETag对象数组进行操作，为了附件独立唯一性我们不直接使用合并后的文件，通过api进行文件拷贝副本使用
     *
     * @param mergeFileParams 分片上传参数
     * @return 文件地址
     */
    @ApiOperation("华为云合并分片")
    @PostMapping("/huawei/merge/file")
    public R<String> mergeFile(@RequestBody @Valid MergeFileParams mergeFileParams) {
        try {
            String fileUrl = huaWeiObsService.mergeFile(mergeFileParams);
            return R.ok(fileUrl);
        } catch (Exception e) {
            return R.fail("华为云合并分片失败：" + e.getMessage());
        }
    }

}
